package cn.iotnova.opus.presenter;

import android.util.Log;

import androidx.annotation.NonNull;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import cn.iotnova.opus.utils.OpusUtils;

public abstract class DecodeOpusPresenter {
    public static int BUFFER_LENGTH = 80;
    private static boolean isCancel;
    private static String decodeOpusFilePath;
    public static int DEFAULT_AUDIO_SAMPLE_RATE = 16000;
    public static int DEFAULT_OPUS_CHANNEL = 1;

    private static final String getTAG() {
        return DecodeOpusPresenter.class.getSimpleName();
    }

    public void decodeOpusFile(@NonNull String path, boolean newThreadRun) {
        Log.i(getTAG(), "decodeOpusFile: " + path + ", newThreadRun: " + newThreadRun);
        decodeOpusFilePath = path;
        isCancel = false;
        if (!newThreadRun) {
            try {
                opusFileDecoder(false, 1, null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            (new Thread((new Runnable() {
                public final void run() {
                    try {
                        opusFileDecoder(false, 1, null);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }))).start();
        }

    }

    public void readFile(@NonNull String path, boolean newThreadRun) {
        Log.i(getTAG(), "decodeOpusFile: " + path + ", newThreadRun: " + newThreadRun);
        decodeOpusFilePath = path;
        isCancel = false;
        if (!newThreadRun) {
            try {
                opusFileDecoder(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            (new Thread((new Runnable() {
                public final void run() {
                    try {
                        opusFileDecoder(false);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }))).start();
        }

    }


    public void cancelDecode() {
        isCancel = true;
    }

    private void opusFileDecoder(boolean needDecoder) throws IOException {
        if (decodeOpusFilePath == null || decodeOpusFilePath.length() == 0) {
            opusDecodeFinish();
        } else {
            long decoderHandler = OpusUtils.createDecoder(DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_OPUS_CHANNEL);
            FileInputStream fis = null;

            try {
                fis = new FileInputStream(decodeOpusFilePath);
            } catch (Exception e) {
                opusDecodeFinish();
                return;
            }

            BufferedInputStream bis = new BufferedInputStream(fis);

            while(!isCancel) {
                byte[] bufferArray = new byte[BUFFER_LENGTH];
                int read = -1;

                try {
                    read = bis.read(bufferArray, 0, bufferArray.length);
                } catch (Exception e) {
                }

                if (read < 0) {
                    Log.i(getTAG(), "OpusFileDecoder compare");
                    break;
                }

                if (needDecoder) {
                    short[] decodeBufferArray = new short[bufferArray.length * 4];
                    int size = OpusUtils.decode(decoderHandler, bufferArray, decodeBufferArray);
                    if (size <= 0) {
                        Log.e(getTAG(), "opusDecode error : " + size);
                        break;
                    }

                    short[] decodeArray = new short[size];
                    System.arraycopy(decodeBufferArray, 0, decodeArray, 0, size);
                    opusDecode(decodeArray);
                } else {
                    opusDecode(byteArrayToShortArray(bufferArray));
                }
            }

            OpusUtils.destroyDecoder(decoderHandler);
            bis.close();
            fis.close();
            opusDecodeFinish();
        }
    }

    @NonNull
    public short[] byteArrayToShortArray(@NonNull byte[] byteArray) {
        short[] shortArray = new short[byteArray.length / 2];
        ByteBuffer.wrap(byteArray).order(ByteOrder.nativeOrder()).asShortBuffer().get(shortArray);
        return shortArray;
    }

    public void opusDecode(@NonNull short[] formatShortArray) {
    }

    public void opusDecodeFinish() {
    }



    public void opusDecode(DecodeOpusPresenter $this, @NonNull short[] formatShortArray) {
    }


    void opusFileDecoder(boolean var1, int var2, Object var3) throws IOException {
        if (var3 != null) {
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: opusFileDecoder");
        } else {
            if ((var2 & 1) != 0) {
                var1 = true;
            }

            opusFileDecoder(var1);
        }
    }

    /*
    // $FF: synthetic method
    static void opusFileDecoder(boolean var1, int var2, Object var3) throws IOException {
        if (var3 != null) {
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: opusFileDecoder");
        } else {
            if ((var2 & 1) != 0) {
                var1 = true;
            }

            opusFileDecoder(var1);
        }
    }

    // $FF: synthetic method
    public static void readFile(String var1, boolean var2, int var3, Object var4) {
        if (var4 != null) {
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: readFile");
        } else {
            if ((var3 & 2) != 0) {
                var2 = true;
            }

            readFile(var1, var2);
        }
    }

    // $FF: synthetic method
    public static void decodeOpusFile(String var1, boolean var2, int var3, Object var4) {
        if (var4 != null) {
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: decodeOpusFile");
        } else {
            if ((var3 & 2) != 0) {
                var2 = true;
            }

            decodeOpusFile(var1, var2);
        }
    }
     */
}
